'''
1. 在测试视频(OpenCV安装目录\sources\samples\data)上，使用基于混合高斯模型的背景提取算法，提取前景并显示(显示二值化图像，前景为白色)。
2. 在1基础上，将前景目标进行分割，进一步使用不同颜色矩形框标记，并在命令行窗口中输出每个矩形框的位置和大小。
3. 安装ImageWatch，并在代码中通过设置断点，观察处理中间结果图像。

扩展作业：
4. 使用光流估计方法，在前述测试视频上计算特征点，进一步进行特征点光流估计。

'''

import  cv2

videoFileName = r'.\vtest.avi'

# 第1-2题 运行请取消注释
cap = cv2.VideoCapture(videoFileName)
fgbg = cv2.createBackgroundSubtractorMOG2()
thresh = 200

while True:
    ret, frame = cap.read()
    if not ret: #没读到当前帧的话，结束
        break

    fgmask = fgbg.apply(frame)
    _, fgmask = cv2.threshold(fgmask, 30, 0xff, cv2.THRESH_BINARY)

    bgImage = fgbg.getBackgroundImage()
    # 返回的第一个是所处理的图像
    _, cnts, _ = cv2.findContours(image=fgmask.copy(), mode= cv2.RETR_EXTERNAL,method= cv2.CHAIN_APPROX_SIMPLE)
    count = 0
    for c in cnts:
        area = cv2.contourArea(c)
        if (area<thresh):
            continue # 面积小于阈值，则下一个
        count += 1

        x,y,w,h = cv2.boundingRect(c)
        cv2.rectangle(frame, (x,y), (x+w,y+h), (0,0xff,0), 2)
        print('目标%d 位置为：左上（%d，%d）至右下（%d，%d）'% (count,x,y,x+w,y+h))
        print('目标%d 大小为：%d'% (count,w*h))
    print('共检测到：',count,"个目标",'\n')
    cv2.imshow('foregroundMask', fgmask) #输出二值化图像
    cv2.imshow("frame", frame)
    cv2.imshow("background", bgImage)

    key = cv2.waitKey(30) #每一帧间隔30ms
    if key ==27: # esc退出
        break

cap.release()
cv2.destroyAllWindows()

'''pycharm没有imagewatch插件'''

# 第四题
# 角点检测参数
feature_params = dict(maxCorners = 100, qualityLevel =0.3,minDistance=7,
                      blockSize=7)
# LK光流参数
lk_params = dict(winSize=(15,15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS| cv2.TERM_CRITERIA_COUNT,10,0.03))
cap = cv2.VideoCapture(videoFileName)

# 计算第一帧特征点
ret, prev = cap.read()
prevGray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)
p0 =cv2.goodFeaturesToTrack(prevGray, mask=None, **feature_params)

while True:
    ret, frame = cap.read()
    if not ret: #没读到当前帧的话，结束
        break
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 计算光流
    p1, st, err = cv2.calcOpticalFlowPyrLK(prevGray,gray,p0,None, **lk_params)

    # 选取好的跟踪点
    goodPoints = p1[st==1]
    goodPrevPoints = p0[st==1]
    #     在结果图中叠加画出来的特征点，计算出来的光流向量
    res = frame.copy()
    drawColor = (0,0,255)
    for i, (cur,prev) in enumerate(zip(goodPoints, goodPrevPoints)):
        x0,y0=cur.ravel()
        x1,y1=prev.ravel()
        cv2.line(res, (x0,y0), (x1,y1), drawColor)
        cv2.circle(res, (x0, y0), 3, drawColor)

    #     更新上一帧
    prevGray = gray.copy()
    p0 = goodPoints.reshape(-1,1,2)
    #     显示计算结果图像
    cv2.imshow('goodPoints',res)
    key = cv2.waitKey(30) #每一帧间隔30ms
    if key ==27: # esc退出
        break

cap.release()
cv2.destroyAllWindows()



















